/*
 * Article:
 *  SystemVerilog Random Stability
 *
 * Description:
 *  This file has example 2.1, 2.2 and 2.3
 * 
 * Run instructions
 * (use run_questa.sh instead of run_vcs.sh to run with Mentor simulator):
 *  ./run_vcs.sh randomstability2.sv +define+EX_2 +define+EX_2_1
 *  ./run_vcs.sh randomstability2.sv +define+EX_2 +define+EX_2_2
 *  ./run_vcs.sh randomstability2.sv +define+EX_2 +define+EX_2_3
 *
 *  Example 2.4 is not shown in the article. In this example, we see an
 *  object newed within the thread. So, by hierarchical seeding rules ..
 *  you'll see that the first random number generated by the thread is
 *  used to initialize `p_th`s internal RNG.
 *  ./run_vcs.sh randomstability2.sv +define+EX_2 +define+EX_2_3
 */
`ifdef EX_2
program automatic test;
    class pkt;
        rand logic [31:0] saddr, daddr, etype;
    endclass: pkt

    initial begin
        pkt p, p_th;
        int unsigned var_a, var_b, var_c;

        `ifdef EX_2_1
        // Object new after for-loop
        for (int ii=0; ii<5; ii++) begin
            var_a = $urandom();
            $display("urandom before object new 0x%x", var_a);
        end
        p = new();
        `endif

        `ifdef EX_2_2
        // Object new before for-loop
        p = new();
        for (int ii=0; ii<5; ii++) begin
            var_a = $urandom();
            $display("urandom after object new 0x%x", var_a);
        end
        `endif

        `ifdef EX_2_3
        // 1. object new
        p = new();
        p.randomize();
        $display("p->saddr 0x%x daddr 0x%x etype 0x%x", p.saddr, p.daddr, p.etype);
        // 2. fork thread
        fork
        begin
            for (int ii=0; ii<5; ii++) begin
                var_b = $urandom();
                $display("thread-block urandom 0x%x", var_b);
            end
        end
        join
        // 3. program for-loop
        for (int ii=0; ii<5; ii++) begin
            var_a = $urandom();
            $display("program-block urandom  0x%x", var_a);
        end
        `endif

        `ifdef EX_2_4
        p = new();
        p.randomize();
        $display("p->saddr 0x%x daddr 0x%x etype 0x%x", p.saddr, p.daddr, p.etype);
        fork
        begin
            p_th = new();
            p_th.randomize();
            $display("p_th->saddr 0x%x daddr 0x%x etype 0x%x", p_th.saddr, p_th.daddr, p_th.etype);
            for (int ii=0; ii<5; ii++) begin
                var_b = $urandom();
                $display("thread-block urandom 0x%x", var_b);
            end
        end
        join

        for (int ii=0; ii<5; ii++) begin
            var_a = $urandom();
            $display("program-block urandom  0x%x", var_a);
        end
        `endif

    end

endprogram
`endif

